package com.xiechuang.util.copy;

import org.dozer.DozerBeanMapper;
import org.dozer.loader.api.BeanMappingBuilder;
import org.dozer.loader.api.TypeMappingOptions;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description DozerMapper是一个Java Bean的转换组件，它可以将一个对象递归拷贝到另外一个对象，支持简单属性映射，复杂类型映射，双向映射，隐式显式映射以及递归映射。
 * @Author xiechuang
 * @Date 2021/10/25
 */
public class DozerMapperUtil {

    /**
     * 单例DozerBeanMapper对象
     */
    private static DozerBeanMapper dozerBeanMapper = new DozerBeanMapper();

    /**
     * 将source对象中的属性值复制到target对象的同名属性中
     *
     * @param source
     * @param target
     */
    public static void copyProperties(Object source, Object target) {
        dozerBeanMapper.map(source, target);
    }

    /**
     * 将source对象中的属性值复制到新建target对象的同名属性中
     *
     * @param source
     * @param targetClass
     * @return
     */
    public static <T> T copyProperties(Object source, Class<T> targetClass) {
        if (source == null) {
            return null;
        }
        return dozerBeanMapper.map(source, targetClass);
    }

    /**
     * 将source对象中的属性值复制到新建target对象的同名属性中，当属性值是null时不赋值，适用于对象修改
     *
     * @param source
     * @param target
     * @return
     */
    public static void copyPropertiesNotNull(final Object source, final Object target) {
        WeakReference weakReference = new WeakReference(new DozerBeanMapper());
        DozerBeanMapper mapper = (DozerBeanMapper) weakReference.get();
        mapper.addMapping(new BeanMappingBuilder() {
            @Override
            protected void configure() {
                mapping(source.getClass(), target.getClass(), TypeMappingOptions.mapNull(false), TypeMappingOptions.mapEmptyString(false));
            }
        });
        mapper.map(source, target);
        mapper.destroy();
        weakReference.clear();
    }

    /**
     * list对象拷贝
     *
     * @param sourceList
     * @param targetClass
     * @return
     */
    public static <T> List<T> copyList(List sourceList, Class<T> targetClass) {
        List<T> targetClassList = new ArrayList<>();
        if (targetClassList != null) {
            for (Object source : sourceList) {
                T t = DozerMapperUtil.copyProperties(source, targetClass);
                targetClassList.add(t);
            }
        }
        return targetClassList;
    }

}
